package com.mf.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mf.bo.CodeDateScopedBo;
import com.mf.bo.DateScopedBo;
import com.mf.bo.calculateHistory.CalculateHistoryBo;
import com.mf.bo.calculateHistory.SumDateCalculateBo;
import com.mf.entity.Code;
import com.mf.entity.CodeHistory;
import com.mf.entity.WeekCodeHistory;
import com.mf.exceptions.GraceException;
import com.mf.mapper.CodeHistoryMapper;
import com.mf.mapper.WeekCodeHistoryMapper;
import com.mf.service.ICodeHistoryService;
import com.mf.service.IWeekCodeHistoryService;
import com.mf.service.utils.numericalProcedure.CalculateProcedure.CalculateProcedure1;
import com.mf.service.utils.numericalProcedure.NumericalProcedure1;
import com.mf.utils.StockGatherUtils;
import com.mf.vo.StockGatherVo;
import org.apache.calcite.plan.Strong;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 股票历史周数据 服务实现类
 * </p>
 *
 * @author mf
 * @since 2024-06-21
 */
@Service
public class WeekCodeHistoryServiceImpl extends ServiceImpl<WeekCodeHistoryMapper, WeekCodeHistory> implements IWeekCodeHistoryService {
    @Resource
    private ICodeHistoryService codeHistoryService;

    @Resource
    private WeekCodeHistoryMapper weekCodeHistoryMapper;

    @Resource
    private CodeHistoryMapper codeHistoryMapper;
    @Override
    @DS("code_history")
    public Map<String, List<CodeHistory>> findAllDate(DateScopedBo dateScopedBo) {
        final LambdaQueryWrapper<CodeHistory> queryWrapper = new LambdaQueryWrapper<>();
        if (dateScopedBo.getStartDate() != null && dateScopedBo.getEndDate() != null) {
            queryWrapper.between(CodeHistory::getD, dateScopedBo.getStartDate(), dateScopedBo.getEndDate());
        }
        //按照时间字段进行排序
        queryWrapper.orderByAsc(CodeHistory::getDm).orderByAsc(CodeHistory::getD);
        final List<CodeHistory> codeHistories = codeHistoryMapper.selectList(queryWrapper);
        // 根据代码库编号对代码历史记录进行分组
        final Map<String, List<CodeHistory>> collect = codeHistories.stream().collect(Collectors.groupingBy(CodeHistory::getDm));

        // 初始化计算历史业务对象列表
        List<CodeHistory> codeHistoryList1 = new ArrayList<>();

        // 对每个代码库分组进行计算处理
        collect.forEach((dm, codeHistoryList) -> {
            // 根据代码历史记录集合提取并封装股票聚合信息
            final StockGatherVo stockGather = StockGatherUtils.getStockGather(codeHistoryList);
            // 使用计算程序1对股票聚合信息进行计算，得到计算历史业务对象

            for (int i = 0; i < codeHistoryList.size(); i++) {
                final String _dm = NumericalProcedure1.isBuyableDay(stockGather, i);
                final HashMap<String, Object> map = new HashMap<>();
                final CodeHistory codeHistory = new CodeHistory();
                if(dm != null){
                    codeHistory.setDm(dm);
                    codeHistory.setD(codeHistoryList.get(i).getD());
                    codeHistoryList1.add(codeHistory);
                }
            }

        });
        return codeHistoryList1.stream().collect(Collectors.groupingBy(CodeHistory::getDm));
    }

    /**
     * 根据基准日期获取这个日期之前一年的周数据
     *
     * @param codeDateScopedBo 时间范围
     * @return List<WeekCodeHistory>
     */
    @Override
    public List<CodeHistory> getCodeListHistoryByDate(CodeDateScopedBo codeDateScopedBo) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate date = LocalDate.parse(codeDateScopedBo.getStartDate(), formatter);
        LocalDate localDate = date.minusMonths(14);
        String startDate = localDate.format(formatter);

        LambdaQueryWrapper<WeekCodeHistory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.between(WeekCodeHistory::getD, startDate, codeDateScopedBo.getEndDate());
        queryWrapper.eq(WeekCodeHistory::getDm, codeDateScopedBo.getDm());

        List<WeekCodeHistory> weekCodeHistories = weekCodeHistoryMapper.selectList(queryWrapper);

        if (weekCodeHistories.isEmpty()) {
            return new ArrayList<>();
        }
        // 如果查询的日期等于周结束日期，则直接返回
        if (!weekCodeHistories.get(weekCodeHistories.size() - 1).getD().equals(codeDateScopedBo.getEndDate())) {
            setWeekEndHistory(weekCodeHistories, codeDateScopedBo, formatter);
        }

        List<CodeHistory> codeHistories = new ArrayList<>();
        for (WeekCodeHistory weekCodeHistory : weekCodeHistories) {
            final CodeHistory codeHistory = new CodeHistory();
            BeanUtils.copyProperties(weekCodeHistory, codeHistory);
            codeHistories.add(codeHistory);
        }

        return codeHistories;
    }

    /**
     * 对最近一周的数据计算获得
     */
    private void setWeekEndHistory(List<WeekCodeHistory> weekCodeHistoryList,
                                                    DateScopedBo dateScopedBo,
                                                    DateTimeFormatter formatter) {
        final DateScopedBo dateScopedBo1 = new DateScopedBo();
        // 获取最近一周数据
        WeekCodeHistory LastWeekCodeHistory = weekCodeHistoryList.get(weekCodeHistoryList.size() - 1);
        dateScopedBo1.setStartDate(LastWeekCodeHistory.getD());
        dateScopedBo1.setEndDate(dateScopedBo.getEndDate());
        final LocalDate date = LocalDate.parse(LastWeekCodeHistory.getD(), formatter);
        // 获取最新周数据
        final LambdaQueryWrapper<CodeHistory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.between(CodeHistory::getD, dateScopedBo1.getStartDate(), dateScopedBo1.getEndDate());
        queryWrapper.eq(CodeHistory::getDm, LastWeekCodeHistory.getDm());
        final List<CodeHistory> codeHistories = codeHistoryService.list(queryWrapper);

        final WeekCodeHistory weekCodeHistory = new WeekCodeHistory();
        boolean flag = false;
        for (int i = 0; i < codeHistories.size(); i++) {
            CodeHistory codeHistory = codeHistories.get(i);
            final LocalDate date1 = LocalDate.parse(codeHistory.getD());
            if (date1.isAfter(date)) {
                // 设置开盘价
                if (!flag) {
                    flag = true;
                    weekCodeHistory.setO(codeHistory.getO());
                    weekCodeHistory.setDm(codeHistory.getDm());
                    weekCodeHistory.setH(BigDecimal.ZERO);
                    weekCodeHistory.setL(codeHistory.getL());
                }
                // 设置最高价
                if (weekCodeHistory.getH().compareTo(codeHistory.getH()) < 0) {
                    weekCodeHistory.setH(codeHistory.getH());
                }
                // 设置最低价
                if (weekCodeHistory.getL().compareTo(codeHistory.getL()) > 0) {
                    weekCodeHistory.setL(codeHistory.getL());
                }
                // 设置收盘价
                if (i == codeHistories.size() - 1) {
                    weekCodeHistory.setD(codeHistory.getD());
                    weekCodeHistory.setC(codeHistory.getC());
                }
            }
        }
        weekCodeHistoryList.add(weekCodeHistory);
    }


    /**
     * 批量保存 添加周数据
     */
    @Override
    public void saveBatchAll(DateScopedBo dateScoped, List<Code> codeList) {
        String type = "wn";
        for (Code code : codeList) {
            final List<CodeHistory> historyList = codeHistoryService.getHistoryList(dateScoped, code.getDm(), type);
            if (historyList.isEmpty()) {
                System.out.println(code.getDm() + "没有数据=============");
                continue;
            }
            System.out.println("添加====" + code.getDm());
            for (CodeHistory codeHistory : historyList) {
                final WeekCodeHistory weekCodeHistory = new WeekCodeHistory();
                BeanUtils.copyProperties(codeHistory, weekCodeHistory);
                weekCodeHistoryMapper.insert(weekCodeHistory);
            }
        }
    }
}
